﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace NetworkingProjectJoined
{
    static class TriviaServer
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {

            Server server = new Server();
            server.startServer();
        }
    }

    class Server
    {
        ServerForm form;
        private bool acceptClients;
        List<ClientHandler> clients;
        List<ClientHandler> unnamedClients;
        Thread waitForClientsThread;
        public Server()
        {
            acceptClients = true;
            clients = new List<ClientHandler>();
        }
        public void startServer()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            form = new ServerForm();
            waitForClientsThread = new Thread(waitForClients);
            waitForClientsThread.Start();
            Application.Run(form);
            foreach (ClientHandler c in clients)
            {
                c.signalBegin();
                c.sendQuestion("what is 1+1", "0", "1", "2", "3","2");
            }
            Application.Run(new ShowQuestion("What is 1+1", "2"));

            ScoreScreen scoreScreen = new ScoreScreen();
            clients.Sort();
            foreach (ClientHandler c in clients)
            {
                scoreScreen.addTeamScore(c.name + ": " + c.score);
            }
            Application.Run(scoreScreen);
        }


        public void waitForClients()
        {
            Thread checkClientNames = new Thread(checkClientNamesThread);
            
            IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
            TcpListener tcpListener = new TcpListener(ipAddress, 9001);
            tcpListener.Start();
            TcpClient client;
             unnamedClients = new List<ClientHandler>();
             checkClientNames.Start();
            //only loop if we are still accepting clients
            while (acceptClients)
            {
                client = tcpListener.AcceptTcpClient();
                //accept clients may have changed while we are waiting for another one
                if (acceptClients)
                {
                    Console.WriteLine("Client Accepted");
                    ClientHandler clientHandler = new ClientHandler(client); //create a new client
                    unnamedClients.Add(clientHandler);
                    clientHandler.startClient(); //start connection on a new thread
                    
                }

                
            }
        }
        private void checkClientNamesThread()
        {

            Console.WriteLine("Trhead started checkClientnames");
            while (true)
            {
                for (int i = 0; i < unnamedClients.Count; i++)
                {
               

                    if (unnamedClients[i].name != "")
                    {
                        Console.WriteLine("Client Added with name");
                        form.addClientName(unnamedClients[i].name);
                        clients.Add(unnamedClients[i]);
                          unnamedClients.RemoveAt(i);

                            i--;

                    }
                }
                Thread.Sleep(100);
            }
        }
    }

    class ClientHandler: IComparable
    {
        public int score;
        public string name;
        private TcpClient client;
        private StreamWriter streamWriter;
        private StreamReader streamReader;
        private Thread thread;
        private Thread waitForAnswerThread;
        private Thread thrdSendQuestion;
        string answer;
        public ClientHandler(TcpClient clientSocket)
        {
            name = "";
            score = 0;
            client = clientSocket;
            streamWriter = new StreamWriter(client.GetStream());
            streamReader = new StreamReader(client.GetStream());
            thread = new Thread(clientThread);
            waitForAnswerThread = new Thread(waitForAnswer);
        }
        public void startClient()
        {
            thread.Start();
        }

        private void clientThread()
        {
            try
            {
                name = streamReader.ReadLine();
            }
            catch
            {
                Console.WriteLine("Client Disconnected");
            }
        }


        public void signalBegin()
        {
            streamWriter.WriteLine("begin");
            streamWriter.Flush();
        }

        public void sendQuestion(string question, string a, string b, string c, string d,string answer)
        {
            Question q = new Question(question, a, b, c, d, answer);
            thrdSendQuestion = new Thread(sendQuestionThread);
            thrdSendQuestion.Start(q);
        }
        public void stopQuestionThread()
        {
            thrdSendQuestion.Abort();
         

        }
        public void sendQuestionThread(object o)
        {
            
            Question q = (Question)o;
            streamWriter.WriteLine(q.question);
            streamWriter.Flush();
            streamWriter.WriteLine(q.a);
            streamWriter.Flush();
            streamWriter.WriteLine(q.b);
            streamWriter.Flush();
            streamWriter.WriteLine(q.c);
            streamWriter.Flush();
            streamWriter.WriteLine(q.d);
            streamWriter.Flush();
            if (!waitForAnswerThread.IsAlive)
                waitForAnswerThread.Start();


            waitForAnswerThread.Join();
            if (answer == q.answer)
            {
                score += 10;
            }



        }

        public void waitForAnswer()
        {
            answer = streamReader.ReadLine();
        }

        public int CompareTo(object obj)
        {
            if (obj is ClientHandler)
            {
                ClientHandler cl = (ClientHandler)obj;
                return score.CompareTo(cl.score);
            }
            throw new ArgumentException("object is not Client Handler");
        }

    }

    class Question
    {
        public string question;
        public string answer;
        public string a, b, c, d;
        public Question(string question, string a, string b, string c, string d, string answer)
        {
            this.question = question;
            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
            this.answer = answer;
        }
    }


}
